package Thread;

import org.junit.Test;

import java.util.concurrent.TimeUnit;

/**
 * Thread 的几个方法：
 *        yield()  ：native方法，暂停当前执行的线程对象，并执行其他线程。这个暂停是会放弃CPU资源的，Running-->Runnable
 *        sleep(long millis)  ： native方法,阻塞线程多长时间，毫秒为单位
 *                 1.sleep是帮助其他线程获得运行机会的最好方法，但是如果当前线程获取到的有锁，sleep不会让出锁。
 *                 2. 线程睡眠到期自动苏醒，并返回到可运行状态（就绪），不是运行状态。
 *                 3、sleep()是静态方法，只能控制当前正在运行的线程
 *       start()：启动并执行线程。 NEW--->Runnable
 *       run():线程调用 start() 方法之后，线程状态从Runable----》Running,当线程获取CPU的执行时间片段，线程开始运行了，执行的方法从run()开始。
 *       System.exit()：方法终止Java虚拟机。 此方法采用一个参数，这是传递给调用方的状态代码。类似于使用条件语句打破循环的严酷版本。
 *       stop()   ：
 *       interrupt()  ：设置中断标识，但是这个方法本身是不能直接中断线程的。 示例如test3,如果线程sleep时候，调用interrupt()，线程睡眠被终止，
 *                      并且抛出Java.lang.InterruptedException,调用interrupt方法是在当前线程中打了一个停止标志，并不是真的停止线程。
 *                      当是while循环中，线程在Running,调用interrupt()时候，线程不会被中断
 *       isInterrupted()  ：用这个方法去检测线程是否有设置中断标识,
 *       getPriority()、setPriority()：获取和设置线程的优先级
 *       join()   ：让父线程等待子线程结束之后才能继续运行。 test4()
 *       isDaemon()、setDaemon()：获取线程是否为守护线程，设置线程为守护线程。
 *       currentThread():  native方法  ，获取当前正在执行的线程
 *       isAlive()： 是测试线程是否处于"活动状态"。
 *       activeCount():活着的线程数量
 * <p>
 * <p>
 * 线程的七种状态：
 * public enum State {
          NEW, //new 新建状态
          RUNNABLE, //runnable  就绪状态
          RUNNING   //运行状态
          BLOCKED, //blocked  //阻塞状态
          WAITING, //waiting
          TIMED_WAITING, //timed_waiting
          TERMINATED; //terminated
  }
 * <p>
 * 线程五种状态：
 *         1、新建状态(New): 线程对象被创建后，就进入了新建状态。例如，Thread thread = new Thread()。
 *         2、就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后，其它线程调用了该对象的start()方法，从而来启动该线程。例如，thread.start()。处于就绪状态的线程，随时可能被CPU调度执行。
 *         3、运行状态(Running): 线程获取CPU（cpu时间片）权限进行执行。需要注意的是，线程只能从就绪状态进入到运行状态。
 *         4、阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权，暂时停止运行。直到线程进入就绪状态，才有机会转到运行状态。阻塞的情况分三种：
 *                (01) 等待阻塞 -- 通过调用线程的wait()方法，让线程等待某工作的完成。JVM会把该线程放入等待队列(waitting queue)中。
 *                (02) 同步阻塞 -- 运行(running)的线程在获取对象的同步锁时，若该同步锁被别的线程占用，则JVM会把该线程放入锁池(lock pool)中。
 *                (03) 其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时，线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时，线程重新转入就绪状态。
 * 5、死亡状态(Dead): 线程执行完了或者因异常退出了run()方法，该线程结束生命周期。
 *
 *
 *  在主线程中开启一个Thread线程，然后调用start（）方法，本质上就是通知JVM虚拟机，新开辟一个栈空间，并且在新的线程空间里面，执行run()方法。
 **/


public class Thread_Method_Study {
    volatile int k = 0;

    @Test
    public void test1() {
        Thread thread = new Thread(() -> {
            k++;
        }, "ThreadName1");
        thread.start();
    }

    @Test
    public void test3() {
        Thread thread = new Thread(() -> {
            while (true) {
                k++;
//               try {
//                   Thread.sleep(50000);
//               }catch (InterruptedException ex){
//
//               }
                System.out.println("---------------------" + k);
            }
        }, "ThreadName1");

        thread.start();
        thread.stop();
//        thread2.start();
        // thread.interrupt();

    }

    @Test
    public void test4() {
        // 子线程
        class Child extends Thread {
            public void run() {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
                System.out.println("...");
            }
        }
        // 创建child对象，此时child表示的线程处于NEW状态
        Child child = new Child();
        child.setName("childName");
        // child表示的线程转换为RUNNABLE状态
        child.start();
        // 等待child线程运行完再继续运行
        try {
            child.join();
            System.out.println(Thread.currentThread().getName());
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }


    /**
     * Object 的 wait() 和 notify() 的等待唤醒机制
     */

    @Test
    public void test5() throws InterruptedException {
        Object  object=new Object();
        Thread thread1=new Thread(()->{
            //同步方法
            synchronized (object){
                System.out.println(Thread.currentThread().getName()+" come in");

                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName()+" 被唤醒");
            }
        },"B");

        //这里有个问题，Thread.sleep() 后，线程睡眠后，不继续往下执行了
        Thread thread2=new Thread(()->{

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


            //同步方法
            synchronized (object){
                System.out.println(Thread.currentThread().getName()+" come in");

                object.notifyAll();


                System.out.println(Thread.currentThread().getName()+" 通知其他线程了");
            }
        },"A");
        thread2.start();
        thread1.start();
         Thread.sleep(10000);//让主线程睡眠，保证子线程全部执行完
        System.out.println("两个线程启动啦，没有我主线程的事情啦");
    }
}
